#pragma once
#include <string>
#include "toml_include/toml.hpp"

#define CHECK(x, y) x.contains(y) && (x.count(y) != 0)

class ConfigureException : public std::exception
{
public:
	ConfigureException(std::string msg)
		: errorMsg(msg)
	{}
	std::string what()
	{
		return errorMsg.c_str();
	}
private:
	std::string errorMsg;
};

class CConfigure
{
public:
	CConfigure() = default;

	int openConfigure(std::string path)
	{
		try
		{
			std::ifstream ifs(path, std::ios_base::binary);
			if (!ifs.good())
			{
				std::cout << "config file read error" << std::endl;
				LOGERROR("config file read error");
				return 0;
			}
			m_config = toml::parse(ifs, path);
		}
		catch (toml::syntax_error e)
		{
			std::cout << "config file parse error" << std::endl;
			LOGERROR("config file parse error");
			return 0;
		}

		return 1;
	}

	//float  integer  string  floating vector<T>
	template<typename T>
	T getConfigValue(std::string tableName, std::string configName, T defaultValue)
	{
		T configValue = defaultValue;
		try
		{
			if (CHECK(m_config, tableName))
			{
				const toml::value main_table = m_config.as_table().at(tableName);
				configValue = toml::find_or<T>(main_table, configName, std::move(defaultValue));
			}
			else
			{
				std::string err_msg = tableName + " table is invalid";
				std::cout << err_msg << std::endl;
				LOGERROR(err_msg);
			}
		}
		catch (toml::type_error e)
		{
			std::string err_msg = std::string("type error ") + e.what();
			std::cout << "type error " << std::endl;
			std::cout << e.what() << std::endl;
			LOGERROR(err_msg);
		}
		catch (std::out_of_range e)
		{
			std::string err_msg = std::string("out_of_range ") + e.what();
			std::cout << "out_of_range" << std::endl;
			std::cout << e.what() << std::endl;
			LOGERROR(err_msg);
		}
		catch (toml::syntax_error e)
		{
			std::string err_msg = std::string("syntax_error ") + e.what();
			std::cout << "syntax_error" << std::endl;
			std::cout << e.what() << std::endl;
			LOGERROR(err_msg);
		}
		return configValue;
	}

private:
	toml::value m_config;
};